//
// Created by HP on 2025/11/28.
//

#include "../include/Headler.h"
#include "../model/Ticket.h"
#include "../model/Order.h"
#include "../model/User.h"
#include "../include/jwt.h"
#include <sstream>
#include <algorithm>

/**
 * @brief 收入统计响应数据字段说明
 *
 * 响应JSON格式包含以下字段：
 * - last24HoursData: 近24小时逐小时收入数据列表，每个元素包含：
 *   - hour: 小时标识（格式：YYYY-MM-DD HH，如 "2024-10-15 09"）
 *   - income: 该小时收入（数值字符串格式）
 * - lastHourIncome: 上一小时收入（数值字符串格式）
 * - lastMonthIncome: 上一个月收入（数值字符串格式）
 * - lastYearIncome: 上一年收入（数值字符串格式）
 * - thisHourIncome: 当前小时收入（数值字符串格式）
 * - thisMonthIncome: 当前月份收入（数值字符串格式）
 * - thisYearIncome: 当前年份收入（数值字符串格式）
 * - todayIncome: 今日收入（数值字符串格式）
 * - updateTime: 数据更新时间（格式：YYYY-MM-DD HH:MM:SS）
 * - yesterdayIncome: 昨日收入（数值字符串格式）
 */
void getIncomeStatistics(const Request& req, Response& res) {
    if (! Middleware::requiredMoney(req)) {
        res.error(401, "Permission denied due to insufficient privileges");
        return;
    }
    std::map<std::string, JsonValue> resMp;
    std::vector<JsonValue> lasthour24(24);
    std::string curHour=getFormattedDateTime();
    std::string lastHour;
    for (int i=1;i<=24;i++){
        std::string hourEnd = addHour(curHour,1-i);
        std::string hourStart= addHour(curHour,-i);
        std::string sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
                             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(hourStart) + "' AND '" + Model::escapeSqlLiteral(hourEnd) + "' "
                                                                                                                                               "AND status = 'finished';";
        auto result=DBConnector::getInstance()->query(sqlStr);
        std::map<std::string, JsonValue> datum;
        datum["Hour"]=JsonValue(hourStart);
        if(result.empty()) {
            datum["Income"]=JsonValue("0");
        } else {
            datum["Income"]=JsonValue(result[0]["income"]);
            if(i==1) lastHour=result[0]["income"];
        }
        lasthour24[i-1]=JsonValue(datum);
    }

    resMp["last24HoursData"]=JsonValue(lasthour24);
    resMp["LastHourIncome"]=JsonValue(lastHour);
    std::string lastMonth = addMonth(curHour,-1);
    std::string lastYear = addYear(curHour,-1);
    std::string sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
                         "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(lastMonth) + "' AND '" + Model::escapeSqlLiteral(curHour) + "' "
                                                                                                                                           "AND status = 'finished';";
    auto result=DBConnector::getInstance()->query(sqlStr);
    if(result.empty()) {
        resMp["lastMonthIncome"]=JsonValue("0");
    } else {
        resMp["lastMonthIncome"]=JsonValue(result[0]["income"]);
    }
    sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(lastYear) + "' AND '" + Model::escapeSqlLiteral(curHour) + "' "
                                                                                                                              "AND status = 'finished';";
    result=DBConnector::getInstance()->query(sqlStr);
    if(result.empty()) {
        resMp["lastYearIncome"]=JsonValue("0");
    } else {
        resMp["lastYearIncome"]=JsonValue(result[0]["income"]);
    }
    std::string thisHour = reSetHour(curHour);
    std::string thisMonth = reSetMonth(curHour);
    std::string thisYear = reSetYear(curHour);

    sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(thisHour) + "' AND '" + Model::escapeSqlLiteral(curHour) + "' "
                                                                                                                              "AND status = 'finished';";
    result=DBConnector::getInstance()->query(sqlStr);
    if(result.empty()) {
        resMp["thisHourIncome"]=JsonValue("0");
    } else {
        resMp["thisHourIncome"]=JsonValue(result[0]["income"]);
    }

    sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(thisMonth) + "' AND '" + Model::escapeSqlLiteral(curHour) + "' "
                                                                                                                               "AND status = 'finished';";
    result=DBConnector::getInstance()->query(sqlStr);
    if(result.empty()) {
        resMp["thisMonthIncome"]=JsonValue("0");
    } else {
        resMp["thisMonthIncome"]=JsonValue(result[0]["income"]);
    }

    sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(thisYear) + "' AND '" + Model::escapeSqlLiteral(curHour) + "' "
                                                                                                                              "AND status = 'finished';";
    result=DBConnector::getInstance()->query(sqlStr);
    if(result.empty()) {
        resMp["thisYearIncome"]=JsonValue("0");
    } else {
        resMp["thisYearIncome"]=JsonValue(result[0]["income"]);
    }

    std::string thisDay = reSetDay(curHour);
    sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(thisDay) + "' AND '" + Model::escapeSqlLiteral(curHour) + "' "
                                                                                                                             "AND status = 'finished';";
    result=DBConnector::getInstance()->query(sqlStr);
    if(result.empty()) {
        resMp["todayIncome"]=JsonValue("0");
    } else {
        resMp["todayIncome"]=JsonValue(result[0]["income"]);
    }

    std::string yesterday = reSetDay(addDay(curHour,-1));
    sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(yesterday) + "' AND '" + Model::escapeSqlLiteral(thisDay) + "' "
                                                                                                                               "AND status = 'finished';";
    result=DBConnector::getInstance()->query(sqlStr);
    if(result.empty()) {
        resMp["yesterdayIncome"]=JsonValue("0");
    } else {
        resMp["yesterdayIncome"]=JsonValue(result[0]["income"]);
    }

    resMp["updateTime"] = JsonValue(getFormattedDateTime());
    res.success(resMp);
}

void getIncomeSourceAnalysis(const Request& req, Response& res) {
    if (! Middleware::requiredMoney(req)) {
        res.error(401, "Permission denied due to insufficient privileges");
        return;
    }

    std::map<std::string, JsonValue> resMp;
    std::map<std::string, JsonValue> data;
    std::string sqlStr = "SELECT "
                         "SUM(o.totalPrice) AS price, t.type AS ticketType , SUM(o.quantity) AS cnt "  // 移除字段后的多余逗号
                         "FROM orders o "  // 移除逗号，改用显式JOIN
                         "JOIN tickets t ON t.id = o.ticketId "
                         "WHERE o.status = 'finished' "
                         "GROUP BY t.type;";
    auto result = DBConnector::getInstance()->query(sqlStr);
    data["dimension"]=JsonValue("车次类型");
    std::vector<JsonValue> dataSource;
    if (result.empty()) {
        std::map<std::string, JsonValue> dataItem1;
        std::map<std::string, JsonValue> dataItem2;
        std::map<std::string, JsonValue> dataItem3;
        std::map<std::string, JsonValue> dataItem4;

        dataItem1["name"]=JsonValue("火车");
        dataItem1["value"]=JsonValue("0");
        dataItem1["count"]=JsonValue("0");
        dataItem1["percentage"]=JsonValue("0");
        dataSource.push_back(dataItem1);

        dataItem2["name"]=JsonValue("高铁");
        dataItem2["value"]=JsonValue("0");
        dataItem2["count"]=JsonValue("0");
        dataItem2["percentage"]=JsonValue("0");
        dataSource.push_back(dataItem2);

        dataItem3["name"]=JsonValue("飞机");
        dataItem3["value"]=JsonValue("0");
        dataItem3["count"]=JsonValue("0");
        dataItem3["percentage"]=JsonValue("0");
        dataSource.push_back(dataItem3);

        dataItem4["name"]=JsonValue("汽车");
        dataItem4["value"]=JsonValue("0");
        dataItem4["count"]=JsonValue("0");
        dataItem4["percentage"]=JsonValue("0");
        dataSource.push_back(dataItem4);
    } else {
        double sum=0;
        for (auto& row : result) {
            sum+=std::stod(row["price"]);
        }
        for (auto& row : result) {
            std::map<std::string, JsonValue> dataItem;
            dataItem["name"]=JsonValue(ticketTypeToStr(row["ticketType"]));
            dataItem["value"]=JsonValue(row["price"]);
            dataItem["count"]=JsonValue(row["cnt"]);
            dataItem["percentage"]=JsonValue(std::to_string(std::stod(row["price"]) / sum * 100));
            dataSource.emplace_back(dataItem);
        }
    }
    data["dataSource"]=JsonValue(dataSource);
    resMp["data"]=data;
    res.success(resMp);
}

void getIncomeTrend(const Request& req, Response& res) {
    if (! Middleware::requiredMoney(req)) {
        res.error(401, "Permission denied due to insufficient privileges");
        return;
    }

    std::string start_date = req.query_param("start_date");
    std::string end_date = req.query_param("end_date");

//    std::cout<<"user"<<std::endl;

    std::map<std::string, JsonValue> resMp;
    std::vector<JsonValue> dataSource;
    while(addDay(start_date,1) <= end_date) {
        std::string thisDay = addDay(start_date,1);
        std::string sqlStr = "SELECT SUM(orders.totalPrice) AS income FROM orders "
                             "WHERE updatedAt BETWEEN '" + Model::escapeSqlLiteral(start_date) + "' AND '" + Model::escapeSqlLiteral(thisDay) + "' ""AND status = 'finished';";
        auto result = DBConnector::getInstance()->query(sqlStr);
        std::map<std::string, JsonValue> dataItem;
        dataItem["date"]=JsonValue(start_date);
        if (result.empty()) {
            dataItem["income"]=JsonValue("0");
        } else {
            dataItem["income"]=JsonValue(result[0]["income"]);
        }
        dataSource.emplace_back(dataItem);
        start_date = thisDay;
    }

    resMp["data"]=JsonValue(dataSource);
    res.success(resMp);
}